package cn.nzcong.jpress.addon.articlesync.platform;

import cn.nzcong.jpress.addon.articlesync.common.Exception.AuthException;
import cn.nzcong.jpress.addon.articlesync.common.Exception.ExternalServiceException;
import cn.nzcong.jpress.addon.articlesync.common.Exception.InternalServiceException;
import cn.nzcong.jpress.addon.articlesync.common.util.HttpUtil;
import cn.nzcong.jpress.addon.articlesync.enums.PlatformEnum;
import cn.nzcong.jpress.addon.articlesync.vo.PlatformVerifyVo;
import cn.nzcong.jpress.addon.articlesync.vo.config.JianshuConfig;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 简书平台
 *
 * @author zecong.nian
 */
public class PlatformJianShu extends BasePlatform<JianshuConfig> {
    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public PlatformEnum getPlatformEnum() {
        return PlatformEnum.JIAN_SHU;
    }

    @Override
    public PlatformVerifyVo doVerify(JianshuConfig config) {
        boolean isValid = true;
        String reason = "";
        String userId = "";
        String nickname = "";
        try{
            if(config == null){
                throw new AuthException("账号配置为空");
            } else if(!config.isEnable()){
                throw new AuthException("配置未开启");
            }
            String slug = config.getSlug();
            if(StringUtils.isBlank(slug)){
                throw new AuthException("slug未配置");
            }
            Long notebook =config.getNotebook();
            if(notebook == null){
                throw new AuthException("notebook未配置");
            }
            if(StringUtils.isBlank(config.getCookie())){
                throw new AuthException("cookie未配置");
            }
            String respJson = io.jboot.utils.HttpUtil.httpGet("https://www.jianshu.com/author/current_user",
                    Collections.EMPTY_MAP, this.toHttpHeader(config));
            JSONObject respObj = JSONObject.parseObject(respJson);
            if(!respObj.containsKey("slug")){
                throw new AuthException("cookie已过期，请更新设置");
            }
            getNoteMap(notebook);
            if(!slug.equalsIgnoreCase(respObj.getString("slug"))){
                throw new AuthException("cookie对应slug为：%s", respObj.getString("slug"));
            }
            userId = respObj.getString("id");
            nickname = respObj.getString("nickname");
        } catch (AuthException e){
            isValid = false;
            reason = e.getMessage();
        }
        return PlatformVerifyVo.builder()
                .enable(config.isEnable())
                .isValid(isValid)
                .reason(reason)
                .platformName(getPlatformEnum().getName())
                .platformDisplayName(getPlatformEnum().getDisplayName())
                .userId(userId)
                .nickname(nickname)
                .build();
    }

    @Override
    protected void _doPublishArticle(String title, String article, String author, String tags, String categories) {
        Long noteId = this.getOldNote(title);
        if(noteId == null || noteId < 1){
            throw new InternalServiceException("笔记ID为空");
        }
        Long lastCompiledAt = this.autoSave(noteId, title, article);
        this.jianshuPublish(noteId);
    }

    @Override
    protected String _doUploadImg(String imgUrl){
        String respStr = io.jboot.utils.HttpUtil.httpPost("https://www.jianshu.com/upload_images/fetch",
                Collections.EMPTY_MAP,
                this.getHttpHeader(),
                new JSONObject(){{
                    put("url", imgUrl);
                }}.toJSONString());
        JSONObject resp = JSONObject.parseObject(respStr);
        if(resp.containsKey("error")){
            throw new AuthException(resp.getString("error"));
        }
        System.out.println("jianshu-uploadImg >>>" + imgUrl + " <<<" + resp);
        return resp.getString("url");
    }


    private Map<String, String> getHttpHeader(){
        return toHttpHeader(super.getConfigObj());
    }

    private Map<String, String> toHttpHeader(JianshuConfig conf){
        return new HashMap<String, String>(){{
            put("cookie", conf.getCookie());
            put("accept", "application/json");
            put("Content-Type", "application/json");
        }};

    }

    private Long getOldNote(String title){
        Long notebookId = super.getConfigObj().getNotebook();
        Map<String, String> notesMap = this.getNoteMap(notebookId);
        Long oldNoteId = null;
        if(notesMap != null && notesMap.size() > 0){
            Map.Entry<String, String> noteEntry = notesMap.entrySet().stream()
                    .filter(e->title.equalsIgnoreCase(e.getValue()))
                    .findFirst()
                    .orElse(null);
            oldNoteId = noteEntry == null || noteEntry.getKey() == null
                    ? null
                    : Long.valueOf(noteEntry.getKey());
        }
        if(oldNoteId == null){
            return createNote(title);
        }
        return oldNoteId;
    }

    /**
     * 使用标题创建记事本
     *
     * @param title
     * @return
     */
    private Long createNote(String title){
        Long notebookId = super.getConfigObj().getNotebook();
        JSONObject data = new JSONObject(){{
            put("notebook_id", String.valueOf(notebookId));
            put("title", title);
            put("at_bottom", false);
        }};
        String respStr = io.jboot.utils.HttpUtil.httpPost("https://www.jianshu.com/author/notes",
                Collections.EMPTY_MAP,
                this.getHttpHeader(),
                data.toJSONString());
        JSONObject resp = JSONObject.parseObject(respStr);
        if(resp.containsKey("error")){
            throw new AuthException(resp.getString("error"));
        }
        return resp.getLong("id");
    }

    /**
     * 调用保存接口保存文章
     *
     * @param noteId
     * @param title
     * @param content
     */
    private Long autoSave(Long noteId, String title, String content){
        JSONObject data = new JSONObject(){{
            put("id", String.valueOf(noteId));
            put("autosave_control", System.currentTimeMillis() / 1000);
            put("title", title);
            put("content", content);
        }};
        String respStr = HttpUtil.doPutHttpRequest("https://www.jianshu.com/author/notes/" + noteId,
                this.getHttpHeader(),
                data.toJSONString());
        JSONObject resp = JSONObject.parseObject(respStr);
        if(resp.containsKey("error")){
            throw new AuthException(resp.getString("error"));
        }
        return resp.getLong("last_compiled_at");
    }

    private Map<String, String> getNoteMap(Long notebookId){
        String respStr = io.jboot.utils.HttpUtil.httpGet(String.format("https://www.jianshu.com/author/notebooks/%s/notes", String.valueOf(notebookId)),
                Collections.EMPTY_MAP, this.getHttpHeader());
        if(!respStr.startsWith("[")){
            JSONObject resp = JSONObject.parseObject(respStr);
            if(resp.containsKey("error")){
                throw new AuthException("文集错误：%s", resp.getString("error"));
            }
            throw new ExternalServiceException("文集错误，返回非列表数据：%s", resp.getString("respStr"));
        } else {
            List<JSONObject> noteList = JSONArray.parseArray(respStr, JSONObject.class);
            return noteList == null ? Collections.EMPTY_MAP
                    : noteList.stream() .collect(Collectors
                            .toMap(json -> json.getString("id"),
                                    json -> json.getString("title"),
                                    (o1, o2) -> o1));
        }
    }

    /**
     * 发布简书
     *
     * @param noteId
     * @return
     */
    private Long jianshuPublish(Long noteId){
        String respStr = io.jboot.utils.HttpUtil.httpPost(String.format("https://www.jianshu.com/author/notes/%s/publicize", String.valueOf(noteId)),
                Collections.EMPTY_MAP,
                this.getHttpHeader(),
                "{}");

        JSONObject resp = JSONObject.parseObject(respStr);
        if(resp.containsKey("error")){
            throw new AuthException(resp.getString("error"));
        }
        return resp.getLong("last_compiled_at");
    }

}
